home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 109
/
EnigmaAmiga109CD.iso
/
dalla rivista
/
amiga.free
/
sorgenti vari
/
wolfedit2 2.0.4 source.sit
/
WolfEdit2 2.0.4 Source
/
UMapListDoc.p
< prev
next >
Wrap
Text File
|
1997-06-24
|
42KB
|
1,789 lines
unit UMapListDoc;
interface
uses
UWolfDoc, UFree, UCursors;
const
firstEncounterCmd = 450;
var
gMultiEncounter: boolean;
gEncounter: integer;
procedure IUMapListDoc;
implementation
uses
{$IFC Demo}
UDemo,
{$ELSEC}
UEditDoors, UEditObjects, UEditEnemies, UEditOther, {}
UBigArt, UMultiArt,
{$ENDC}
UDialog, UXWindow, {}
UInstall, UMusic, UCTables, UEditArt, {}
UEditWalls, {}
UScenarioInfo;
const
noMemForLevelAlrtID = 128;
couldntOperateOnLevelAlrtID = 129;
buildFileBusyAlrtID = 137;
invalidAltNextLevelAlrtID = 143;
requiresVersionAlrtID = 144;
couldntSetCreatorAlrtID = 145;
buildScenarioCmd = 250;
rebuildScenarioCmd = 251;
scenarioInfoCmd = 260;
importMusicCmd = 261;
lastEncounterCmd = 452;
editWallsCmd = 406;
editDoorsCmd = 407;
editObjectsCmd = 408;
editOtherCmd = 410;
editEnemiesCmd = 411;
titleArtCmd = 270;
intermissionArtCmd = 271;
bjArtCmd = 272;
faceArt320Cmd = 273;
faceArt512Cmd = 274;
faceArt640Cmd = 275;
getPsychedArtCmd = 276;
titleColoursCmd = 280;
gameColoursCmd = 281;
intermissionColoursCmd = 282;
stdWallListID = 137;
mapListBrgrID = 146;
musicListBrgrID = 147;
wallListBrgrID = 137;
firstLevelBrgrID = 200;
maxLevelBrgrID = 299;
firstCustomArtBrgrID = $2000;
firstImagePictID = $4000;
firstCustID = 128;
miscBrgrNameIDBase = 1000;
saveLevelsDlogID = 136;
wolfEditFileItem = 10;
scenarioFileItem = 11;
type
CustHandle = ^CustPtr;
CustPtr = ^CustRecord;
CustRecord = array[0..255] of integer;
var
gStdWallList: WallListHandle;
procedure IUMapListDoc;
begin
gStdWallList := WallListHandle(GetResource('BRGR', stdWallListID));
end;
procedure UpdateArtEditPalettes (mapList: TMapListDoc);
procedure CheckWindow (win: TWindow);
begin
if member(win, TArtEditDialog) then
with TArtEditDialog(win) do
if fPalette <> nil then
fPalette.Invalidate;
end;
begin {UpdateArtEditPalettes}
mapList.EachWindowDo(CheckWindow);
end;
procedure TMapListDoc.SetupMenus;
var
cmd: integer;
thisEncounterCmd: integer;
minEncounterCmd: integer;
begin
EnableCmd(scenarioInfoCmd);
EnableCmd(buildScenarioCmd);
EnableCmd(rebuildScenarioCmd);
thisEncounterCmd := firstEncounterCmd + fVersion.encounter - 1;
minEncounterCmd := firstEncounterCmd + fVersion.minEncounter - 1;
for cmd := firstEncounterCmd to lastEncounterCmd do
if cmd >= minEncounterCmd then
EnableCmd(cmd);
CheckCmd(thisEncounterCmd, true);
EnableCmd(editWallsCmd);
EnableCmd(editDoorsCmd);
EnableCmd(editObjectsCmd);
EnableCmd(editOtherCmd);
EnableCmd(editEnemiesCmd);
EnableCmd(titleArtCmd);
EnableCmd(getPsychedArtCmd);
EnableCmd(intermissionArtCmd);
EnableCmd(bjArtCmd);
EnableCmd(faceArt320Cmd);
EnableCmd(faceArt512Cmd);
EnableCmd(faceArt640Cmd);
EnableCmd(titleColoursCmd);
EnableCmd(gameColoursCmd);
EnableCmd(intermissionColoursCmd);
EnableCmd(importMusicCmd);
inherited SetupMenus;
end;
procedure TMapListDoc.DoMenuCommand (cmdNumber: integer);
const
secondEncounterCmd = firstEncounterCmd + 1;
begin
case cmdNumber of
scenarioInfoCmd:
EditScenarioInfo(self);
buildScenarioCmd:
DoBuildScenario;
rebuildScenarioCmd:
DoRebuildScenario;
editWallsCmd:
EditWalls(self);
firstEncounterCmd..lastEncounterCmd: begin
SetEncounter(cmdNumber - firstEncounterCmd + 1);
{$IFC NOT Demo}
UpdateArtEditPalettes(self);
{$ENDC}
end;
{$IFC Demo}
editDoorsCmd, editObjectsCmd, editOtherCmd, editEnemiesCmd,{}
titleArtCmd, getPsychedArtCmd, intermissionArtCmd, bjArtCmd, {}
faceArt320Cmd, faceArt512Cmd, faceArt640Cmd, titleColoursCmd, {}
intermissionColoursCmd, gameColoursCmd, importMusicCmd:
OnlyInFullVersion;
{$ELSEC}
editDoorsCmd:
EditDoors(self);
editObjectsCmd:
EditObjects(self);
editOtherCmd:
EditOther(self);
editEnemiesCmd:
EditEnemies(self);
titleArtCmd:
EditBigArt(self, titleArt);
getPsychedArtCmd:
EditBigArt(self, getPsychedArt);
intermissionArtCmd:
EditBigArt(self, intermissionArt);
bjArtCmd:
EditMultiArt(self, bjArt);
faceArt320Cmd:
EditMultiArt(self, faceArt320);
faceArt512Cmd:
EditMultiArt(self, faceArt512);
faceArt640Cmd:
EditMultiArt(self, faceArt640);
titleColoursCmd:
EditColours(self, titleCTabID);
intermissionColoursCmd:
EditColours(self, intermissionCTabID);
gameColoursCmd:
EditColours(self, gameCTabID);
importMusicCmd:
EditMusic(self);
{$ENDC}
otherwise
inherited DoMenuCommand(cmdNumber);
end;
end;
function NewWallArtList: WallArtListHandle;
begin
NewWallArtList := WallArtListHandle(NewHandle(sizeof(WallArtList)));
end;
procedure DisposeWallArtList (wal: WallArtListHandle);
var
i: integer;
procedure DisposeWallArtPair (wale1, wale2: WallArtListEntry);
begin
if wale2.art <> wale1.art then
DisposHandle(Handle(wale2.art));
DisposeHandle(Handle(wale1.art));
end;
begin {DisposeWallArtList}
for i := 0 to 31 do
DisposeWallArtPair(wal^^[2 * i], wal^^[2 * i + 1]);
DisposHandle(Handle(wal));
end;
procedure DisposeObjectArtList (p: TObjectArtList);
var
q: TObjectArtList;
begin
while p <> nil do begin
q := p;
p := p.next;
DisposHandle(Handle(q.art));
dispose(q);
end;
end;
procedure RequiresVersion (name: string; v: integer);
var
d: integer;
begin
if v mod 10 = 0 then
d := 1
else
d := 2;
ParamText(name, StringOf(v / 100 : 1 : d), '', '');
DoAlert(requiresVersionAlrtID);
end;
procedure ChangeImageMask (var mask: CustomMaskSet; code: integer; value: boolean);
begin
if value then begin
mask := mask + [code];
end
else
mask := mask - [code];
end;
procedure TMapListDoc.IMapListDoc;
begin
IDocument(wolfEdit2DocType);
fVersion.wolfEdit := unknownVersion;
fVersion.encounter := 1;
fVersion.minEncounter := 1;
fName := nil;
fPict := nil;
fTitleMusic := DefaultTitleMusic;
fInterMusic := DefaultBetweenLevelsMusic;
fNumLevels := 0;
fIndex := nil;
fWallArt := nil;
fObjectArt := nil;
fImageCache := gDefaultImageCache;
fOwnImageCache := false;
fImagesChanged := false;
{$IFC SaveAsScenario}
fFileCreator := gCreator;
{$ENDC}
fHasScenarioFile := false;
fScenarioVRefNum := 0;
fScenarioFileName := '';
fMusic := nil;
fMiscBrgrs := nil;
fMiscRsrcs := nil;
end;
procedure TMapListDoc.DisposeContents;
var
i: integer;
p: LevelInfoHandle;
h: LevelHandle;
m: TMusicRsrcList;
b: TBrgrList;
r: TRsrcList;
begin
DisposHandle(Handle(fName));
DisposHandle(Handle(fPict));
for i := 1 to fNumLevels do begin
FreeObject(fIndex^^[i].map);
with fIndex^^[i] do begin
p := info;
h := resource;
end;
if p <> nil then
DisposeLevelInfo(p);
if h <> nil then
DisposeLevel(h);
end;
DisposHandle(Handle(fIndex));
fIndex := nil;
fNumLevels := 0;
if fWallArt <> nil then begin
DisposeWallArtList(fWallArt);
fWallArt := nil;
end;
if fObjectArt <> nil then begin
DisposeObjectArtList(fObjectArt);
fObjectArt := nil;
end;
if fOwnImageCache & (fImageCache <> nil) then begin
fImageCache.Free;
fImageCache := nil;
fOwnImageCache := false;
end;
while fMusic <> nil do begin
m := fMusic;
fMusic := fMusic.next;
DisposHandle(m.song);
DisposHandle(m.midi);
dispose(m);
end;
while fMiscBrgrs <> nil do begin
b := fMiscBrgrs;
fMiscBrgrs := b.next;
DisposHandle(b.brgr);
dispose(b);
end;
while fMiscRsrcs <> nil do begin
r := fMiscRsrcs;
fMiscRsrcs := fMiscRsrcs.next;
DisposHandle(r.data);
dispose(r);
end;
end;
procedure TMapListDoc.SetNumLevels (n: integer);
begin
if fIndex = nil then
fIndex := IndexHandle(NewHandle(0));
if fIndex <> nil then begin
fNumLevels := n;
SetHandleSize(Handle(fIndex), n * sizeof(IndexEntry));
end;
end;
procedure TMapListDoc.DoNew;
begin
fVersion.wolfEdit := thisVersion;
fVersion.encounter := gEncounter;
NewLevel;
end;
{$IFC SaveAsScenario}
var
gInited: boolean;
gFileType: integer;
function SaveAsFilter (dlog: DialogPtr; var e: EventRecord; var itemHit: integer): boolean;
begin
if not gInited then begin
SetDlgIValue(dlog, gFileType, 1);
gInited := true;
end;
SaveAsFilter := false;
end;
function SaveAsHook (item: integer; dlog: DialogPtr): integer;
begin
case item of
wolfEditFileItem, scenarioFileItem:
if gFileType <> item then begin
SetDlgIValue(dlog, gFileType, 0);
gFileType := item;
SetDlgIValue(dlog, gFileType, 1);
end;
otherwise
;
end;
SaveAsHook := item;
end;
function TMapListDoc.DoSaveAs: boolean;
var
where: Point;
reply: SFReply;
defaultName: Str255;
prompt: Str255;
begin
SetPt(where, 100, 75);
if fHasFile then
defaultName := fFileName
else
defaultName := '';
prompt := GetString(gStdIDBase + saveAsPromptStrID)^^;
ParamText(fFileName, '', '', '');
if fFileCreator = 'WOLF' then
gFileType := scenarioFileItem
else
gFileType := wolfEditFileItem;
gInited := false;
SFPPutFile(where, prompt, defaultName, @SaveAsHook, reply, saveLevelsDlogID, @SaveAsFilter);
if reply.good then begin
HaveFile(reply.vRefNum, reply.fName);
if gFileType = scenarioFileItem then begin
fFileCreator := 'WOLF';
fFileType := 'MAPS';
end
else begin
fFileCreator := gCreator;
fFileType := 'W3L2';
end;
DoSaveAs := Write;
end
else
DoSaveAs := false;
end;
function TMapListDoc.Write: boolean;
var
info: FInfo;
done: boolean;
fileName: Str255;
procedure Check (result: OSErr);
begin
if result <> noErr then begin
ErrorAlert(couldntSetCreatorAlrtID, fFileName, result);
Write := false;
exit(Write);
end;
end;
begin {Write}
done := inherited Write;
if done then begin
fileName := fFileName;
Check(GetFInfo(fileName, fVRefNum, info));
info.fdCreator := fFileCreator;
Check(SetFInfo(fileName, fVRefNum, info));
end;
Write := done;
end;
{$ENDC}
procedure TMapListDoc.NewLevel;
var
prevInfo: LevelInfoHandle;
begin
SetNumLevels(fNumLevels + 1);
with fIndex^^[fNumLevels] do begin
info := NewLevelInfo;
resource := nil;
map := nil;
if fNumLevels > 1 then
prevInfo := fIndex^^[fNumLevels - 1].info
else
prevInfo := nil;
with info^^ do begin
mapListEntry.nextLevel := -1;
mapListEntry.altNextLevel := -1;
mapListEntry.parTime := 60;
if prevInfo <> nil then begin
mapListEntry.majorFloor := prevInfo^^.mapListEntry.majorFloor;
mapListEntry.minorFloor := prevInfo^^.mapListEntry.minorFloor + 1;
end
else begin
mapListEntry.majorFloor := 1;
mapListEntry.minorFloor := 1;
end;
music := DefaultLevelMusic;
end;
end;
end;
procedure TMapListDoc.OpenLevel (num: integer);
var
map: TMap;
h: LevelHandle;
begin
h := fIndex^^[num].resource;
map := fIndex^^[num].map;
if map = nil then begin
new(map);
map.IMap(self, num);
fIndex^^[num].map := map;
if h <> nil then
map.LoadFromResource(h);
map.MakeWindow;
end;
map.fView.fFrame.fWindow.Select;
end;
procedure TMapListDoc.CloseLevel (num: integer);
var
map: TMap;
procedure Check (result: OSErr);
begin
if result <> noErr then begin
LevelError('close', num, result);
exit(CloseLevel);
end;
end;
begin {CloseLevel}
map := fIndex^^[num].map;
if map <> nil then begin
Check(UpdateResource(num));
map.Free;
end;
end;
procedure TMapListDoc.InsertLevel (num: integer; p: LevelInfoHandle; h: LevelHandle);
var
i: integer;
begin
SetNumLevels(fNumLevels + 1);
for i := fNumLevels downto num + 1 do
fIndex^^[i] := fIndex^^[i - 1];
with fIndex^^[num] do begin
info := p;
resource := h;
map := nil;
end;
Changed;
end;
function TMapListDoc.CutLevel (num: integer; var p: LevelInfoHandle; var h: LevelHandle): OSErr;
var
i: integer;
e: IndexEntry;
procedure Check (result: OSErr);
begin
if result <> noErr then begin
CutLevel := result;
exit(CutLevel);
end;
end;
begin
Check(UpdateResource(num));
e := fIndex^^[num];
p := e.info;
h := e.resource;
FreeObject(e.map);
for i := num to fNumLevels - 1 do
fIndex^^[i] := fIndex^^[i + 1];
SetNumLevels(fNumLevels - 1);
Changed;
CutLevel := noErr;
end;
function TMapListDoc.GetDiskSpaceNeeded (var dataBytes, rsrcBytes: longint): OSErr;
const
mapListHeaderSize = 2 * sizeof(integer);
mapListEntrySize = sizeof(MapListEntry);
musicListHeaderSize = 2 * sizeof(integer);
musicListEntrySize = sizeof(integer);
var
n: integer;
h: LevelHandle;
procedure Check (result: OSErr);
begin
if result <> noErr then begin
GetDiskSpaceNeeded := result;
exit(GetDiskSpaceNeeded);
end;
end;
begin
dataBytes := 0;
rsrcBytes := (mapListHeaderSize + musicListHeaderSize) + (mapListEntrySize + musicListEntrySize) * fNumLevels;
for n := 1 to fNumLevels do begin
Check(UpdateResource(n));
h := fIndex^^[n].resource;
if h <> nil then
rsrcBytes := rsrcBytes + GetHandleSize(Handle(h));
end;
GetDiskSpaceNeeded := noErr;
end;
procedure TMapListDoc.AugmentFileTypes (var numTypes: integer; var typeList: SFTypeList);
begin
numTypes := 3;
typeList[1] := 'W3dL';
typeList[2] := 'MAPS';
end;
function TMapListDoc.ReadFromFile (refNum: integer): OSErr;
var
n, maxLevel, id: integer;
h: Handle;
mapList: MapListHandle;
musicList: MusicListHandle;
info: FInfo;
fileName: Str255;
procedure Check (result: OSErr);
begin
if (result <> noErr) & (result <> resNotFound) then begin
ReadFromFile := result;
exit(ReadFromFile);
end;
end;
procedure InitInfo (var p: LevelInfoRecord; n: integer);
begin
if (mapList <> nil) & (n <= mapList^^.numLevels) then begin
p.mapListEntry := mapList^^.entries[n];
if fVersion.wolfEdit = unknownVersion then
if n < mapList^^.numLevels then
if p.mapListEntry.nextLevel = -1 then
p.mapListEntry.nextLevel := n;
end
else
with p.mapListEntry do begin
nextLevel := -1;
altNextLevel := -1;
parTime := 60;
majorFloor := 1;
minorFloor := n;
end;
if musicList <> nil then
p.music := musicList^^.levels[n]
else
p.music := DefaultLevelMusic;
end;
procedure GetWallArt (wle: WallListEntry; var wale: WallArtListEntry);
begin
wale.darkFlag := wle.darkFlag;
wale.mirrorFlag := wle.mirrorFlag;
wale.art := WallArtHandle(GetResource('BRGR', wle.brgrID));
end;
procedure ReadWallArt;
var
wallList: WallListHandle;
i: integer;
begin
wallList := WallListHandle(Get1Resource('BRGR', wallListBrgrID));
if wallList <> nil then begin
fWallArt := NewWallArtList;
HLock(Handle(fWallArt));
for i := 0 to 63 do
GetWallArt(wallList^^.entries[i], fWallArt^^[i]);
for i := 0 to 63 do
DetachResource(fWallArt^^[i].art);
HUnlock(Handle(fWallArt));
ReleaseResource(Handle(wallList));
end;
end;
procedure ReadImages;
var
pict: PicHandle;
cust: CustHandle;
iType: CustomImageType;
code: integer;
mask: CustomMaskSet;
h: Handle;
begin
pict := PicHandle(Get1Resource('PICT', firstImagePictID));
if pict <> nil then begin
InstallOwnImageCache;
fImageCache.InstallPicture(pict);
ReleaseResource(Handle(pict));
{InstallCustomMask;}
for iType := wallImage to objectImage do begin
cust := CustHandle(Get1Resource('CUST', firstCustID + ord(iType)));
if cust <> nil then begin
mask := [];
for code := 0 to 255 do
if cust^^[code] <> 0 then begin
mask := mask + [code];
fImageCache.InstallImagePict(pict, cust^^[code], GetImageNum(iType, code));
end;
HLock(Handle(fImageCache));
fImageCache.fCustomMask[iType] := mask;
HUnlock(Handle(fImageCache));
ReleaseResource(Handle(cust));
end;
end;
h := Get1Resource('CUST', firstCustID + 2);
Check(ResError);
if h <> nil then begin
BlockMove(h^, @fImageCache.fUserMask, sizeof(fImageCache.fUserMask));
ReleaseResource(h);
end;
end;
end;
{$IFC NOT Demo}
procedure ReadObjectArt;
var
id: integer;
p: TObjecTArtList;
begin
for id := firstSpriteBrgrID to lastSpriteBrgrID do begin
h := Get1Resource('BRGR', id);
Check(ResError);
if h <> nil then begin
DetachResource(h);
InstallObjectArt(id, ObjectArtHandle(h));
Check(MemError);
end;
end;
end;
procedure ReadMusic;
var
p: TMusicRsrcList;
song, midi: Handle;
rID: integer;
rType: ResType;
rName: Str255;
i, n: integer;
begin
n := Count1Resources('Midi');
for i := 1 to n do begin
midi := Get1IndResource('Midi', i);
Check(ResError);
GetResInfo(midi, rID, rType, rName);
song := Get1Resource('SONG', rID);
if song <> nil then begin
new(p);
Check(MemError);
p.id := rID;
p.name := rName;
p.song := song;
p.midi := midi;
p.next := fMusic;
fMusic := p;
DetachResource(song);
DetachResource(midi);
end
else
ReleaseResource(midi);
end;
end;
procedure ReadMiscBrgr (id: integer);
var
p: TBrgrList;
rID: integer;
rType: ResType;
rName: Str255;
begin
h := Get1Resource('BRGR', id);
if ResError <> resNotFound then
Check(ResError);
if h <> nil then begin
new(p);
Check(MemError);
GetResInfo(h, rID, rType, rName);
DetachResource(h);
p.brgrID := id;
p.name := rName;
p.brgr := h;
p.next := fMiscBrgrs;
fMiscBrgrs := p;
end;
end;
procedure ReadMiscBrgrs;
var
id: integer;
begin
for id := firstMiscBrgrID to lastMiscBrgrID do
if not (id in [137, 138, 146, 147]) then
ReadMiscBrgr(id);
end;
{$ENDC}
procedure ReadPict;
begin
fPict := PicHandle(GetResource('PICT', levelPictID));
if fPict <> nil then
DetachResource(Handle(fPict));
end;
procedure ReadMiscRsrcs (rType: ResType);
var
p: TRsrcList;
i: integer;
h: Handle;
rName: Str255;
begin
i := 1;
while true do begin
h := Get1IndResource(rType, i);
if h = nil then
exit(ReadMiscRsrcs);
new(p);
Check(MemError);
GetResInfo(h, id, rType, rName);
p.rType := rType;
p.id := id;
p.name := rName;
p.data := h;
p.next := fMiscRsrcs;
fMiscRsrcs := p;
DetachResource(h);
i := i + 1;
end;
end;
begin {ReadFromFile}
ChangeCursor(gWatch);
{$IFC SaveAsScenario}
fileName := fFileName;
Check(GetFInfo(fileName, fVRefNum, info));
fFileType := info.fdType;
fFileCreator := info.fdCreator;
{$ENDC}
h := Get1Resource('Vers', 128);
if h <> nil then begin
if GetHandleSize(h) = sizeof(fVersion) then
fVersion := VersionHandle(h)^^
else begin
fVersion.wolfEdit := VersionHandle(h)^^.wolfEdit;
fVersion.encounter := VersionHandle(h)^^.encounter;
fVersion.minEncounter := fVersion.encounter;
end;
ReleaseResource(h);
end
else begin
fVersion.wolfEdit := unknownVersion;
fVersion.encounter := 1;
end;
if not gMultiEncounter then begin
fVersion.encounter := 3;
fVersion.minEncounter := 3;
end;
if fVersion.wolfEdit > thisVersion then begin
RequiresVersion(fFileName, fVersion.wolfEdit);
Check(suppressErr);
end;
mapList := MapListHandle(Get1Resource('BRGR', mapListBrgrID));
Check(ResError);
musicList := MusicListHandle(Get1Resource('BRGR', musicListBrgrID));
Check(ResError);
fTitleMusic := musicList^^.title;
fInterMusic := musicList^^.betweenLevels;
maxLevel := mapList^^.numLevels;
SetNumLevels(maxLevel);
if MemError <> noErr then
fNumLevels := 0;
Check(MemError);
HLock(Handle(fIndex));
for n := 1 to fNumLevels do
with fIndex^^[n] do begin
info := NewLevelInfo;
InitInfo(info^^, n);
resource := nil;
map := nil;
end;
HUnlock(Handle(fIndex));
for n := 1 to maxLevel do begin
id := mapList^^.firstLevelID + n - 1;
h := Get1Resource('BRGR', id);
Check(ResError);
if h <> nil then begin
DetachResource(h);
fIndex^^[n].resource := LevelHandle(h);
end;
end;
ReadWallArt;
ReadImages;
{$IFC NOT Demo}
ReadObjectArt;
ReadMusic;
ReadMiscBrgrs;
{$ENDC}
ReadPict;
ReadMiscRsrcs('snd ');
ReadMiscRsrcs('csnd');
ReadMiscRsrcs('INST');
ReadFromFile := noErr;
end;
function TMapListDoc.WriteToFile (refNum: integer): OSErr;
var
h: Handle;
procedure Abort (result: OSErr);
begin
if h <> nil then
DisposHandle(h);
WriteToFile := result;
exit(WriteToFile);
end;
procedure Error (lev: integer; result: OSErr);
begin
Abort(result);
end;
procedure Check (result: OSErr);
begin
if result <> noErr then
Abort(result);
end;
procedure AddAndRelease (var h: Handle; rType: ResType; rID: integer; rName: Str255);
var
hh: Handle;
begin
hh := h;
AddResource(hh, rType, rID, rName);
if ResError = noErr then begin
h := nil;
WriteResource(hh);
if ResError = noErr then
ReleaseResource(hh);
end;
end;
procedure WriteImages;
var
iType: CustomImageType;
code: integer;
cust: CustHandle;
begin
if fOwnImageCache then begin
HLock(Handle(fImageCache));
with fImageCache do begin
h := Handle(fImageCache.ExtractPicture);
AddAndRelease(h, 'PICT', firstImagePictID, '');
Check(ResError);
for iType := wallImage to objectImage do begin
if fImageCache.fCustomMask[iType] <> [] then begin
h := NewHandle(sizeof(CustRecord));
cust := CustHandle(h);
for code := 0 to 255 do
if code in fImageCache.fCustomMask[iType] then
cust^^[code] := GetImageNum(iType, code)
else
cust^^[code] := 0;
AddAndRelease(h, 'CUST', firstCustID + ord(iType), '');
Check(ResError);
end;
end;
if fUserMask[wallImage] + fUserMask[objectImage] <> [] then begin
h := NewHandle(sizeof(fUserMask));
Check(MemError);
BlockMove(@fUserMask, h^, sizeof(fUserMask));
AddAndRelease(h, 'CUST', firstCustID + 2, '');
end;
end;
HUnlock(Handle(fImageCache));
end;
end;
begin {WriteToFile}
if not FlushWindows then
Check(suppressErr);
h := NewHandle(sizeof(VersionRecord));
Check(MemError);
VersionHandle(h)^^ := fVersion;
VersionHandle(h)^^.wolfEdit := thisVersion;
AddResource(h, 'Vers', 128, '');
Check(ResError);
h := nil;
WriteResources(false, Error);
WriteImages;
WriteToFile := noErr;
end;
function TMapListDoc.UpdateResource (num: integer): OSErr;
var
h, h2: LevelHandle;
map: TMap;
procedure Check (result: OSErr);
begin
if result <> noErr then begin
UpdateResource := result;
exit(UpdateResource);
end;
end;
begin {UpdateResource}
map := fIndex^^[num].map;
h := fIndex^^[num].resource;
if (map <> nil) & ((h = nil) | (map.fChanged)) then begin
gCurrentCursor := GetCursor(watchCursor);
SetCursor(gCurrentCursor^^);
Check(map.CreateResource(h2, concat(GetLevelName(num), ' of ', fFileName)));
if h <> nil then
DisposeLevel(h);
fIndex^^[num].resource := h2;
map.fChanged := false;
end;
UpdateResource := noErr;
end;
{$IFC FALSE}
procedure TMapListDoc.DoInstall;
var
reply: SFReply;
begin
GetInstallFile(reply);
if reply.good then
InstallInFile(reply);
end;
{$ENDC}
{$IFC FALSE}
procedure TMapListDoc.DoInstallIn;
var
reply: SFReply;
begin
GetNewInstallFile(reply);
if reply.good then
InstallInFile(reply);
end;
{$ENDC}
procedure TMapListDoc.DoRebuildScenario;
begin
if not fHasScenarioFile then
DoBuildScenario
else
BuildScenario;
end;
procedure TMapListDoc.DoBuildScenario;
var
reply: SFReply;
where: Point;
begin
if fScenarioFileName = '' then
fScenarioFileName := concat(fFileName, ' Scenario');
SetPt(where, -1, -1);
SFPutFile(where, 'Build Scenario:', fScenarioFileName, nil, reply);
if reply.good then begin
fHasScenarioFile := true;
fScenarioVRefNum := reply.vRefNum;
fScenarioFileName := reply.fName;
BuildScenario;
end;
end;
procedure TMapListDoc.BuildScenario;
var
refNum: integer;
fileOpen: boolean;
result: OSErr;
procedure Error (lev: integer; result: OSErr);
begin
if (result = opWrErr) | (result = fBsyErr) then
ErrorAlert(buildFileBusyAlrtID, fScenarioFileName, result)
else
LevelError('install', lev, result);
if fileOpen then
CloseResFile(refNum);
exit(BuildScenario);
end;
procedure Check (result: OSErr);
begin
if result <> noErr then
Error(0, result);
end;
begin {BuildScenario}
fileOpen := false;
result := FSDelete(fScenarioFileName, fScenarioVRefNum);
Check(Create(fScenarioFileName, fScenarioVRefNum, 'WOLF', 'MAPS'));
HCreateResFile(fScenarioVRefNum, 0, fScenarioFileName);
Check(ResError);
refNum := HOpenResFile(fScenarioVRefNum, 0, fScenarioFileName, fsRdWrPerm);
Check(ResError);
fileOpen := true;
ChangeCursor(gWatch);
WriteResources(true, Error);
CloseResFile(refNum);
fileOpen := false;
Check(ResError);
end;
function TMapListDoc.GetLevelName (levelNum: integer): Str255;
var
p: LevelInfoHandle;
begin
p := fIndex^^[levelNum].info;
GetLevelName := StringOf('Floor ', p^^.mapListEntry.majorFloor : 1, '-', p^^.mapListEntry.minorFloor : 1);
end;
{Write out those resources that go in both WolfEdit files and Scenario files.}
procedure TMapListDoc.WriteResources (installing: boolean; procedure Error (lev: integer; result: OSErr));
var
n, id: integer;
h, hCopy: Handle;
mapList: MapListHandle;
musicList: MusicListHandle;
wallList: WallListHandle;
name: string;
procedure Check (result: OSErr);
begin
if result <> noErr then begin
if mapList <> nil then
DisposeMapList(mapList);
if musicList <> nil then
DisposeMusicList(musicList);
if hCopy <> nil then
DisposHandle(hCopy);
if wallList <> nil then
DisposHandle(Handle(wallList));
Error(n, result);
end;
end;
function ValidateAltNextLevels: OSErr;
var
i, j: integer;
info: LevelInfoHandle;
begin
for i := 1 to fNumLevels do begin
info := fIndex^^[i].info;
j := info^^.mapListEntry.altNextLevel + 1;
if (j < 0) | (j > fNumLevels) then begin
ParamText(GetLevelName(i), '', '', '');
if Ask(invalidAltNextLevelAlrtID) = cancel then begin
ValidateAltNextLevels := suppressErr;
exit(ValidateAltNextLevels);
end;
info^^.mapListEntry.altNextLevel := -1;
end;
end;
ValidateAltNextLevels := noErr;
end;
procedure DeleteRsrc (typ: ResType; id: integer);
var
h: Handle;
begin
SetResLoad(false);
h := Get1Resource(typ, id);
if h <> nil then begin
RmveResource(h);
DisposHandle(h);
end;
SetResLoad(true);
end;
procedure DeleteBrgr (id: integer);
var
h: Handle;
begin
DeleteRsrc('BRGR', id);
end;
procedure AddRsrc (var h: univ Handle; typ: ResType; id: integer; name: string);
begin
DeleteRsrc(typ, id);
AddResource(h, typ, id, name);
Check(ResError);
h := nil;
end;
procedure AddBrgr (var h: univ Handle; id: integer; name: string);
begin
AddRsrc(h, 'BRGR', id, name);
end;
procedure AddRsrcCopy (h: univ Handle; typ: ResType; id: integer; name: string);
var
result: OSErr;
begin
{$IFC FALSE}
Check(HandToHand(h));
hCopy := h;
AddRsrc(hCopy, typ, id, name);
{$ELSEC}
DeleteRsrc(typ, id);
AddResource(h, typ, id, name);
WriteResource(h);
result := ResError;
DetachResource(h);
Check(result);
{$ENDC}
end;
procedure AddBrgrCopy (h: univ Handle; id: integer; name: string);
begin
AddRsrcCopy(h, 'BRGR', id, name);
end;
procedure BackupBrgr (id: integer);
var
h: Handle;
rID: integer;
rType: ResType;
rName: Str255;
begin
if installing then begin
SetResLoad(false);
h := GetResource('BRGR', -id);
if h = nil then begin
h := GetResource('BRGR', id);
if h <> nil then begin
GetResInfo(h, rID, rType, rName);
SetResInfo(h, -id, rName);
end;
end;
if h <> nil then
ReleaseResource(h);
SetResLoad(true);
end;
end;
procedure RestoreBrgr (id: integer);
var
h, bh: Handle;
rID: integer;
rType: ResType;
rName: Str255;
begin
if installing then begin
SetResLoad(false);
bh := GetResource('BRGR', -id);
if bh <> nil then begin
h := GetResource('BRGR', id);
if h <> nil then begin
RmveResource(h);
DisposHandle(h);
end;
GetResInfo(bh, rID, rType, rName);
SetResInfo(bh, id, rName);
ReleaseResource(bh);
end;
SetResLoad(true);
end;
end;
procedure PutWallListEntry (wae: WallArtListEntry; brgrID: integer; var wle: WallListEntry);
begin
wle.darkFlag := wae.darkFlag;
wle.mirrorFlag := wae.mirrorFlag;
wle.brgrID := brgrID;
end;
procedure WriteWallArt;
var
i, brgrID: integer;
art, prevArt: WallArtHandle;
begin
wallList := WallListHandle(NewHandle(sizeof(WallListRecord)));
Check(MemError);
wallList^^ := gStdWallList^^;
if fWallArt <> nil then begin
wallList^^.numEntries := 64;
for i := 0 to 63 do begin
art := fWallArt^^[i].art;
if art = nil then
brgrID := gStdWallList^^.entries[i].brgrID
else if not (odd(i) & (art = prevArt)) then begin
brgrID := firstCustomArtBrgrID + i;
AddBrgrCopy(art, brgrID, StringOf('Wall ', i : 1));
end;
PutWallListEntry(fWallArt^^[i], brgrID, wallList^^.entries[i]);
prevArt := art;
end;
end;
AddBrgr(wallList, wallListBrgrID, 'Wall List');
end;
{$IFC NOT Demo}
procedure WriteObjectArt;
const
maxSprite = lastSpriteBrgrID - firstSpriteBrgrID;
type
SpriteSet = set of 0..maxSprite;
var
p: TObjectArtList;
sprites: SpriteSet;
i, id: integer;
begin
sprites := [];
p := fObjectArt;
while p <> nil do begin
id := p.brgrID;
i := id - firstSpriteBrgrID;
sprites := sprites + [i];
BackupBrgr(id);
AddBrgrCopy(p.art, id, StringOf('Sprite ', i : 1));
p := p.next;
end;
for id := firstSpriteBrgrID to lastSpriteBrgrID do
if not (id - firstSpriteBrgrID in sprites) then
RestoreBrgr(id);
end;
procedure WriteMusic;
type
WordPtr = ^integer;
var
p: TMusicRsrcList;
i: integer;
begin
p := fMusic;
while p <> nil do begin
WordPtr(p.song^)^ := p.id;
AddRsrcCopy(p.song, 'SONG', p.id, p.name);
AddRsrcCopy(p.midi, 'Midi', p.id, p.name);
id := id + 1;
p := p.next;
end;
end;
procedure WriteMiscBrgrs;
var
p: TBrgrList;
begin
p := fMiscBrgrs;
while p <> nil do begin
if p.brgr <> nil then
AddBrgrCopy(p.brgr, p.brgrID, p.name);
p := p.next;
end;
end;
{$ENDC}
procedure SupplyDarkTable;
var
dt: Handle;
begin
if GetMiscBrgr(136) = nil then begin
dt := GetResource('BRGR', 136);
AddBrgrCopy(dt, 136, 'DarkTable');
ReleaseResource(dt);
end;
end;
procedure WritePict;
begin
if fPict <> nil then
AddRsrcCopy(fPict, 'PICT', levelPictID, '');
end;
procedure WriteMiscRsrcs;
var
p: TRsrcList;
begin
p := fMiscRsrcs;
while p <> nil do begin
if p.data <> nil then
AddRsrcCopy(p.data, p.rType, p.id, p.name);
p := p.next;
end;
end;
begin {WriteResources}
if not FlushWindows then
Check(suppressErr);
mapList := nil;
musicList := nil;
hCopy := nil;
wallList := nil;
n := 0;
ChangeCursor(gWatch);
Check(ValidateAltNextLevels);
DeleteBrgr(mapListBrgrID);
DeleteBrgr(musicListBrgrID);
mapList := CreateMapListResource(installing);
Check(MemError);
musicList := CreateMusicListResource;
Check(MemError);
AddResource(Handle(mapList), 'BRGR', mapListBrgrID, 'Map List');
Check(ResError);
ReleaseResource(Handle(mapList));
mapList := nil;
AddResource(Handle(musicList), 'BRGR', musicListBrgrID, 'Music List');
Check(ResError);
ReleaseResource(Handle(musicList));
musicList := nil;
for n := 1 to fNumLevels do begin
Check(UpdateResource(n));
h := Handle(fIndex^^[n].resource);
if h <> nil then begin
Check(HandToHand(h));
hCopy := h;
id := firstLevelBrgrID + n - 1;
DeleteBrgr(id);
name := GetLevelName(n);
if installing then
name := concat(name, ' of ', fFileName);
AddResource(hCopy, 'BRGR', id, name);
Check(ResError);
ReleaseResource(hCopy);
hCopy := nil;
end;
end;
WriteWallArt;
{$IFC NOT Demo}
WriteObjectArt;
WriteMusic;
WriteMiscBrgrs;
{$ENDC}
SupplyDarkTable;
WritePict;
WriteMiscRsrcs;
end;
function TMapListDoc.CreateMapListResource (installing: boolean): MapListHandle;
var
h: MapListHandle;
n: integer;
begin
h := NewMapList(fNumLevels);
if h <> nil then begin
h^^.numLevels := fNumLevels;
h^^.firstLevelID := firstLevelBrgrID;
for n := 1 to fNumLevels do begin
h^^.entries[n] := fIndex^^[n].info^^.mapListEntry;
with h^^.entries[n] do
if n < fNumLevels then
nextLevel := n
else
nextLevel := -1;
end;
end;
CreateMapListResource := h;
end;
function TMapListDoc.CreateMusicListResource: MusicListHandle;
var
h: MusicListHandle;
i: integer;
begin
h := NewMusicList(fNumLevels);
if h <> nil then begin
h^^.title := fTitleMusic;
h^^.betweenLevels := fInterMusic;
for i := 1 to fNumLevels do
h^^.levels[i] := fIndex^^[i].info^^.music;
end;
CreateMusicListResource := h;
end;
procedure TMapListDoc.LevelError (doing: string; lev: integer; result: OSErr);
var
what: string;
alrt: integer;
begin
if (result <> noErr) & (result <> suppressErr) then begin
what := fFileName;
if lev > 0 then
what := concat(GetLevelName(lev), ' of ', what);
case result of
memFullErr:
alrt := noMemForLevelAlrtID;
otherwise
alrt := couldntOperateOnLevelAlrtID;
end;
ParamText('install', what, StringOf(result : 1), '');
DoAlert(alrt);
end;
end;
function TMapListDoc.GetWallArtList: WallArtListHandle;
var
i: integer;
procedure InitEntry (j: integer; d, m: boolean);
begin
with fWallArt^^[j] do begin
art := nil;
darkFlag := d;
mirrorFlag := m;
end;
end;
begin {TMapListDoc.GetWallArtList}
if fWallArt = nil then begin
fWallArt := NewWallArtList;
for i := 0 to 28 do begin
InitEntry(2 * i, false, false);
InitEntry(2 * i + 1, true, false);
end;
InitEntry(58, false, false);
for i := 59 to 62 do
InitEntry(i, false, true);
InitEntry(63, false, false);
end;
GetWallArtList := fWallArt;
end;
{$IFC FALSE}
function TMapListDoc.GetObjectArtList: ObjectArtListHandle;
begin
if fObjectArt = nil then
fObjectArt := NewObjectArtList;
GetObjectArtList := fObjectArt;
end;
{$ENDC}
function TMapListDoc.GetObjectArt (brgrID: integer): ObjectArtHandle;
var
p: TObjectArtList;
begin
p := fObjectArt;
while p <> nil do begin
if p.brgrID = brgrID then begin
GetObjectArt := p.art;
exit(GetObjectArt);
end;
p := p.next;
end;
GetObjectArt := nil;
end;
procedure TMapListDoc.InstallObjectArt (brgrID: integer; art: ObjectArtHandle);
var
p: TObjectArtList;
procedure AddNode;
var
p: TObjectArtList;
begin
if art <> nil then begin
new(p);
if MemError <> noErr then
exit(InstallObjectArt);
p.brgrID := brgrID;
p.art := art;
p.next := fObjectArt;
fObjectArt := p;
end;
end;
procedure DeleteNode (p: TObjectArtList);
var
q: TObjectArtList;
begin
if p = fObjectArt then
fObjectArt := p.next
else begin
q := fObjectArt;
while q.next <> p do
q := q.next;
q.next := p.next;
end;
dispose(p);
end;
begin {TMapListDoc.InstallObjectArt }
p := fObjectArt;
while (p <> nil) & (p.brgrID <> brgrID) do
p := p.next;
if p = nil then
AddNode
else begin
DisposHandle(Handle(p.art));
if art <> nil then
p.art := art
else
DeleteNode(p);
end;
fChanged := true;
end;
function TMapListDoc.GetMiscBrgr (id: integer): Handle;
var
p: TBrgrList;
begin
p := fMiscBrgrs;
while (p <> nil) & (p.brgrID <> id) do
p := p.next;
if p <> nil then
GetMiscBrgr := p.brgr
else
GetMiscBrgr := nil;
end;
procedure TMapListDoc.InstallMiscBrgr (h: Handle; id: integer);
var
p: TBrgrList;
nameH: StringHandle;
begin
p := fMiscBrgrs;
while (p <> nil) & (p.brgrID <> id) do
p := p.next;
if p = nil then begin
new(p);
p.brgrID := id;
p.brgr := nil;
p.next := fMiscBrgrs;
fMiscBrgrs := p;
end;
DisposHandle(p.brgr);
nameH := GetString(miscBrgrNameIDBase + id);
if nameH <> nil then
p.name := nameH^^
else
p.name := '';
p.brgr := h;
end;
function TMapListDoc.GetMiscRsrc (rType: ResType; id: integer): Handle;
var
p: TRsrcList;
begin
p := fMiscRsrcs;
while (p <> nil) & ((p.rType <> rType) or (p.id <> id)) do
p := p.next;
if p <> nil then
GetMiscRsrc := p.data
else
GetMiscRsrc := nil;
end;
procedure TMapListDoc.InstallMiscRsrc (h: Handle; rType: ResType; id: integer; name: string);
var
p: TRsrcList;
begin
p := fMiscRsrcs;
while (p <> nil) & ((p.rType <> rType) or (p.id <> id)) do
p := p.next;
if p = nil then begin
new(p);
p.rType := rType;
p.id := id;
p.data := nil;
p.next := fMiscRsrcs;
fMiscRsrcs := p;
end;
DisposHandle(p.data);
p.name := name;
p.data := h;
end;
procedure TMapListDoc.PlotWall (code: integer; r: Rect);
begin
if WallAvailable(code) then begin
HLock(Handle(fImageCache)); {Set membership testing can MOVE MEMORY!!!}
if code in fImageCache.fCustomMask[wallImage] then
fImageCache.PlotWall(code, r)
else
gDefaultImageCache.PlotWall(code, r);
HUnlock(Handle(fImageCache));
end
else
gDefaultImageCache.PlotUnknown(r);
end;
procedure TMapListDoc.PlotObject (code, dir: integer; r: Rect);
begin
with gVariantObjectTable[code] do
if baseObject >= 0 then begin
PlotObject(baseObject, dir, r);
gDefaultImageCache.PlotImage(extraImage, r);
end
else if ObjectAvailable(code) then begin
HLock(Handle(fImageCache));
if code in fImageCache.fCustomMask[objectImage] then
fImageCache.PlotObject(code, dir, r)
else
gDefaultImageCache.PlotObject(code, dir, r);
HUnlock(Handle(fImageCache));
end
else
gDefaultImageCache.PlotUnknown(r);
end;
procedure TMapListDoc.PlotSound (r: Rect);
begin
gDefaultImageCache.PlotSound(r);
end;
function TMapListDoc.WallAvailable (code: integer): boolean;
begin
HLock(Handle(fImageCache));
if code in fImageCache.fCustomMask[wallImage] then
WallAvailable := true
else
WallAvailable := WallAvailableIn(code, fVersion.Encounter);
HUnlock(Handle(fImageCache));
end;
function TMapListDoc.ObjectAvailable (code: integer): boolean;
begin
HLock(Handle(fImageCache));
if code in fImageCache.fCustomMask[objectImage] then
ObjectAvailable := true
else
ObjectAvailable := ObjectAvailableIn(code, fVersion.Encounter);
HUnlock(Handle(fImageCache));
end;
function TMapListDoc.ItemAvailable (item: MapCell): boolean;
begin
ItemAvailable := WallAvailable(item.wall) & ObjectAvailable(item.obj);
end;
procedure TMapListDoc.InstallWallImage (code, view: integer; gWorld: GWorldPtr);
begin
InstallOwnImageCache;
fImageCache.InstallWallImage(code, view, gWorld);
HLock(Handle(fImageCache));
ChangeImageMask(fImageCache.fCustomMask[wallImage], code, gWorld <> nil);
HUnlock(Handle(fImageCache));
fImagesChanged := true;
Changed;
UpdateImageViews;
end;
procedure TMapListDoc.InstallDoorImage (code: integer; gWorld: GWorldPtr);
begin
InstallOwnImageCache;
fImageCache.InstallDoorImage(code, gWorld);
HLock(Handle(fImageCache));
ChangeImageMask(fImageCache.fCustomMask[objectImage], BAND(code, $FE), gWorld <> nil);
ChangeImageMask(fImageCache.fCustomMask[objectImage], BOR(code, $01), gWorld <> nil);
HUnlock(Handle(fImageCache));
fImagesChanged := true;
Changed;
UpdateImageViews;
end;
procedure TMapListDoc.InstallObjectImage (code: integer; gWorld: GWorldPtr);
begin
InstallOwnImageCache;
fImageCache.InstallObjectImage(code, gWorld);
HLock(Handle(fImageCache));
ChangeImageMask(fImageCache.fCustomMask[objectImage], code, gWorld <> nil);
HUnlock(Handle(fImageCache));
fImagesChanged := true;
Changed;
UpdateImageViews;
end;
procedure TMapListDoc.InstallOwnImageCache;
var
imageCache: TImageCache;
begin
if not fOwnImageCache then begin
new(imageCache);
imageCache.IImageCache;
fImageCache := imageCache;
fOwnImageCache := true;
end;
end;
procedure TMapListDoc.Changed;
begin
fVersion.minEncounter := fVersion.encounter;
inherited Changed;
end;
function TMapListDoc.FlushWindows: boolean;
procedure FlushWindow (win: TWindow);
begin
if member(win, TXWindow) then
if not TXWindow(win).Flush then begin
FlushWindows := false;
exit(FlushWindows);
end;
end;
begin {TMapListDoc.FlushWindows}
FlushWindows := true;
EachWindowDo(FlushWindow);
end;
end.